#include"get_sha1.cpp"
#include"diff.cpp"
#include"init.cpp"
#include"add.cpp"
#include"get_path.cpp"
#include"index.cpp"
#include"time.cpp"
#include"commit.cpp"
#include"file_data_struct.cpp"
#include"diff_cached.cpp"
#include<map>
typedef struct{
    vector<string> help;
    vector<string> option; 
}cmdl;
void add_help(cmdl* c, string m);
void add_option(cmdl* c, string m);
void output_help(cmdl c);
int chose_option(string* order, cmdl* action, int argc);
int main(int argc, char** argv)
{
    system("chcp 65001"); 
    string action[7] = {"diff", "init", "add", "commit", "rm", "mv", "status"};
    cmdl c[7];  //按顺序分别为操作diff、init、add、commit、rm、mv、status
    map<string, int> mp;  
    int i;
    int GETRIGHTOPTION = 0;
    string* get_option = new string[argc-1];
    for(i = 0; i < argc-1; i++)
        get_option[i] = argv[i+1];
    for(i = 0; i < 7; i++)
        mp[action[i]] = i;  //用于方便选择所进行的操作
    add_help(&c[0], "git diff --no-index [<选项>] <路径> <路径>");
    add_help(&c[0], "diff                  显示提交之间、提交和工作区之间等的差异");
    add_help(&c[0], "--cached              查看尚未暂存的某个文件更新了哪些");
    add_option(&c[0], "--cached"), add_option(&c[0], "--no-index");
    add_help(&c[1], "git init [-q | --quiet] [--bare] [--template=<模板目录>] [--shared[=<权限>]] [<目录>]");
    add_help(&c[1], "init                  创建一个空的 Git 仓库或重新初始化一个已存在的仓库");
    add_help(&c[2], "git add [<选项>] [--] <路径规格>...");
    add_help(&c[2], "add                   添加文件内容至索引");
    add_help(&c[2], "-u, --update          更新已跟踪的文件");
    add_help(&c[2], "-A, --all             添加所有改变的已跟踪文件和未跟踪文件");
    add_option(&c[2], "-u"), add_option(&c[2], "--update"), add_option(&c[2], "-A"), add_option(&c[2], "--all");
    add_help(&c[3], "git commit [<选项>] [--] <路径规格>...");
    add_help(&c[3], "commit                记录变更到仓库");
    add_help(&c[3], "-m, --message         提交说明");
    add_help(&c[3], "-a                    直接提交，不用执行add");
    add_option(&c[3], "-m"), add_option(&c[3], "--message"), add_option(&c[3], "-a");
    add_help(&c[4], "git rm [<选项>] [--] <文件>...");
    add_help(&c[4], "rm                    从工作区和索引中删除文件");
    add_help(&c[4], "-f, --force           强制删除");
    add_help(&c[4], "--cached              仅从跟踪清单中删除");
    add_option(&c[4], "-f"), add_option(&c[4], "--force"), add_option(&c[4], "--cached");
    add_help(&c[5], "git mv [<选项>] <源>... <目标>");
    add_help(&c[5], "mv                    移动或重命名一个文件、目录或符号链接");
    add_help(&c[5], "-f, --force           强制移动/重命令，即使目标存在");
    add_option(&c[5], "-f"), add_option(&c[5], "--force");
    add_help(&c[6], "git status [<选项>] [--] <路径规格>...");
    add_help(&c[6], "status                显示工作区状态");
    add_help(&c[6], "-v, --verbose         冗长输出");
    add_help(&c[6], "-s, --short           以简洁的格式显示状态");
    add_option(&c[6], "-v"), add_option(&c[6], "--verbose"), add_option(&c[6], "-s"), add_option(&c[6], "--short");
    if(argc == 1)
    {
        printf("请输入指令，例如：\n");
        for(i = 0; i < 6; i++)
            cout << (c[i].help)[0] << endl;
        return 0;
    }
    if(argc == 2 && (!get_option[0].compare("-h") || !get_option[0].compare("--help")))
    {
            for(i = 0; i < 6; i++)
                cout << (c[i].help)[1] << endl;
            GETRIGHTOPTION = 1;
    }
    else
        GETRIGHTOPTION = chose_option(get_option, c, argc);
    if(!GETRIGHTOPTION)
        printf("无效指令");
}
void add_help(cmdl* c, string m)
{
    (c->help).push_back(m);
}
void add_option(cmdl* c, string m)
{
    (c->option).push_back(m);
}
void output_help(cmdl c)
{
    int i;
    cout << "用法：" << (c.help)[0] << endl;
    for(i = 2; i < (c.help).size(); i++)
        cout << "  " << (c.help)[i] << endl;
}
int chose_option(string* order, cmdl* action, int argc)
{
    if(!order[0].compare("init"))
    {
        if(argc == 2)
        {
            if(build_git_folder(".git"))
                cout << "已初始化空的 Git 仓库位于： ";
            char buf[255];
            getcwd(buf, 255);
            string store_path(buf);
            store_path_in_file(store_path);
            cout << store_path << endl; 
            cout << endl;
            build_store(store_path);
            return 1;
        }
        else if(!order[1].compare("-h") || !order[1].compare("--help"))
            output_help(action[1]);
        else if(argc > 3)
            cout << "无效指令" << endl;
        else
        {
            if(!init_target_folder(order[1]))
                cout << "初始化仓库失败" << endl;
            else
            {
                string store_path;
                store_path = file_path(order[1]);
                cout << "已初始化空的 Git 仓库位于： " << store_path << endl;
                build_store(store_path);
                store_path_in_file(store_path);
                return 1;
            } 
        }
        
    }
    index_file* fh = &fp;
    build_list_struct(&fh, store_path());
    if(!order[0].compare("diff"))
    {
        if(!order[1].compare("-h") || !order[1].compare("--help"))
            output_help(action[0]);
        else if(!order[1].compare(action[0].option[1]))
        {
            if(argc != 5)
            cout << "无效指令" << endl;
            else if(!git_diff(order+2))
            cout << "文件不存在" << endl;
            else
            return 1;
        }
        /*有待开发*/
    }
    else if(!order[0].compare("add"))
    {
        if(!order[1].compare("-h") || !order[1].compare("--help"))
            output_help(action[2]);
        else if(!order[1].compare("-u") || !order[1].compare("--update"))
            cout << "文件追踪已更新" << endl;
        else if(!order[1].compare("-A") || !order[1].compare("--all"))
            cout << "所有改变的已跟踪文件和未跟踪文件已经添加" << endl;
        else
        {
            int i = 1;
            for(; i < argc-1; i++) 
            {
                ifstream f(order[i].c_str());
                if(!f) cout  << order[i] << "不存在，或路径错误" << endl;
                else
                {
                    string SHA1 = hash_sha1("blob", order[i]);
                    string ob_name = SHA1.substr(0, 2);
                    string filename = SHA1.substr(2, 40);
                    ifstream f(order[i].c_str());
                    stringstream ss;
                    ss << f.rdbuf();
                    string data = ss.str();  //zlib(file data);
                    f.close();
                    creat_object(store_path(), ob_name, filename, data);
                    string time = get_time();
                    make_index_file(store_path(), 10064, order[i], SHA1, time);
                }
            }
        }    
    }
    else if(!order[0].compare("commit"))
    {
        if(!order[1].compare("-h") || !order[1].compare("--help"))
            output_help(action[3]);
        else
        {
            int i = 1;
            for(; i < argc-1; i++)
            {  
                commit_file(store_path(), order[i]);
            }
        }
    }
    else if(!order[0].compare("rm"))
    {
        if(!order[1].compare("-h") || !order[1].compare("--help"))
            output_help(action[4]);
        /*有待开发*/
    }
    else if(!order[0].compare("mv"))
    {
        if(!order[1].compare("-h") || !order[1].compare("--help"))
            output_help(action[5]);
        /*有待开发*/
    }
    else if(!order[0].compare("status"))
    {
        if(!order[1].compare("-h") || !order[1].compare("--help"))
            output_help(action[6]);
        /*有待开发*/
    }
    else
    return 0;
}